﻿using System;
using System.Reflection;

namespace BReusable
{
static	class BReflection
	{

		#region MethodWhoCalledMe
		/// <summary>
		/// if this doesn't work try System.Reflection.MethodBase.GetCurrentMethod().Name 
		/// in the method that needs it's name
		/// 
		/// All callers should have
		/// [System.Runtime.CompilerServices.MethodImpl(
		///	System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		///	above their method definition
		/// </summary>
		/// <param name="index">usually 0</param>
		/// <returns></returns>
		[System.Runtime.CompilerServices.MethodImpl(
			System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		#endregion
		public static String MethodWhoCalledMe(int index)
		{
			return MethodInfo(index + 1).Name;
		}

		#region MethodInfo
		/// <summary>
		/// if this doesn't work try System.Reflection.MethodBase.GetCurrentMethod()
		/// in the function that needs its name
		/// 
		/// All callers should have
		/// [System.Runtime.CompilerServices.MethodImpl(
		///	System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		///	above their method definition
		/// </summary>
		/// <param name="index">usually 0</param>
		/// <returns></returns>
		[System.Runtime.CompilerServices.MethodImpl(
			System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		#endregion
		public static MethodBase MethodInfo(int index)
		{
			var stackTrace = new System.Diagnostics.StackTrace(1 + index);
			return stackTrace.GetFrame(index + 1).GetMethod();
            
		}

		#region ClassThatCalledMe

		/// <summary>
		/// All callers should have
		/// [System.Runtime.CompilerServices.MethodImpl(
		///	System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		///	above their method definition
		/// </summary>
		/// <param name="index">usually 0</param>
		/// <returns></returns>
		[System.Runtime.CompilerServices.MethodImpl(
			System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		#endregion
		public static String ClassThatCalledMe(int index)
		{
			return ClassThatCalledMe(MethodInfo(index + 1));
		}
		public static String ClassThatCalledMe(MethodBase methodBase)
		{
			return methodBase.DeclaringType.ToString();
		}

		#region ClassAndMethodWhoCalledMe
		/// <summary>
		/// Used to save the generation of 2 stackTraces to get information about the caller
		/// All callers should have
		/// [System.Runtime.CompilerServices.MethodImpl(
		///	System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
		///	above their method definition
		/// </summary>
		/// <param name="index">usually 0</param>
		/// <returns>class, and method name of the caller</returns>
		[System.Runtime.CompilerServices.MethodImpl(
			System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endregion
		public static Pair<String, String> ClassAndMethodWhoCalledMe(int index)
		{
			var methodInfo=MethodInfo(index+1);
			return new Pair<string, string>(methodInfo.Name, ClassThatCalledMe(methodInfo));
		}


	}
}
